package com.qianniu.napi.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.google.common.base.Strings;
import com.qianniu.napi.admin.entity.*;
import com.qianniu.napi.admin.mapper.LeagueMapper;
import com.qianniu.napi.admin.service.*;
import com.qianniu.napi.common.config.Constants;
import com.qianniu.napi.common.util.HttpUtil;
import com.qianniu.napi.common.util.ObjectUtil;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RBucket;
import org.redisson.api.RList;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class RedisServiceImpl implements IRedisService {

    private static final Logger logger = LoggerFactory.getLogger(RedisServiceImpl.class);
    @Autowired
    private RedissonClient redis;
    @Autowired
    private IUserService userService;
    @Autowired
    private IOemService oemService;
    @Autowired
    private LeagueMapper leagueMapper;
    @Autowired
    private IMerchantService merchantService;
    @Autowired
    private IStoreService storeService;
    @Autowired
    private IFenxiaoService fenxiaoService;
    @Autowired
    private IMerchantAppService merchantAppService;
    @Autowired
    private IMerchantConfigService merchantConfigService;
    @Autowired
    private IFanConfigService fanConfigService;

    public Boolean isnull(String rkey) {
        logger.debug("=========isnull get rkey=" + rkey);
        RBucket<String> bucket = redis.getBucket(rkey);
        return Strings.isNullOrEmpty(bucket.get());
    }

    public Boolean isExists(String rkey) {
        logger.debug("=========isnull get rkey=" + rkey);
        RBucket<String> bucket = redis.getBucket(rkey);
        return bucket.isExists();
    }

    /**
     * 获取原子数
     *
     * @param key
     * @return
     */
    public RAtomicLong getRAtomicLong(String key) {
//        RAtomicLong rAtomicLong = redis.getAtomicLong(key);
        RAtomicLong rAtomicLong = redis.getAtomicLong(key);
        return rAtomicLong;
    }

    public <T> T get(String rkey) {
        logger.debug("=========get rkey=" + rkey);
        RBucket<T> bucket = redis.getBucket(rkey);
        if (!bucket.isExists()) return null;
        T t = bucket.get();
        return t;
    }

    public <T> void set(String rkey, T t) {
        logger.debug("=========set rkey=" + rkey);
        RBucket<T> bucket = redis.getBucket(rkey);
        if (t == null) {
            logger.debug("=========set rkey t=null");
            return;
        }
        bucket.set(t);
    }

    public <T> void setList(String rkey, T t) {
        logger.debug("=========set rkey=" + rkey);
        RList<T> bucket = redis.getList(rkey);
        bucket.add(t);
    }

    public <T> List<T> getList(String rkey) {
        logger.debug("=========getList rkey=" + rkey);
        RList<T> bucket = redis.getList(rkey);
        List<T> list = bucket.get();
        return list;
    }

    public <T> void set(String rkey, T t, long ts, TimeUnit tu) {
        logger.debug("=========set rkey withtimeout=" + rkey);
        RBucket<T> bucket = redis.getBucket(rkey);
        if (t == null) {
            logger.debug("=========set rkey t=null");
            return;
        }
        bucket.set(t, ts, tu);
    }

    public <T> void del(String rkey) {
        logger.debug("=========del rkey=" + rkey);
        RBucket<T> bucket = redis.getBucket(rkey);
        if (bucket.isExists()) bucket.delete();
    }

    public User getUser() {
        logger.debug("=========getUser");
        if (ObjectUtil.getUid() == null) return null;
        return getUser(ObjectUtil.getUid());
    }

    public User getUser(Long uid) {
        logger.debug("=========getUser with uid=" + uid);
        // 1、获取mapp
        String guid = ObjectUtil.getGuid();
        if (uid == null) return null;

        String rkey = Constants.REDIS_APP_USER + uid;
        logger.debug("=========getUser rkey=" + rkey);
        RBucket<User> bucket = redis.getBucket(rkey);

        User user = bucket.isExists() ? bucket.get() : userService.selectById(uid);
        if (user == null&&guid!=null) {
            user = userService.selectOne(new EntityWrapper<User>().eq("guid", guid));
        }
        if (user == null) return null;

        logger.debug("--------------------------------------redis=set=user=" + user);
        if (bucket.get() == null) bucket.set(user, 30, TimeUnit.MINUTES);

        String rgkey = Constants.REDIS_APP_USER_GUID + user.getGuid();
        RBucket<User> rgbucket = redis.getBucket(rgkey);
        if (rgbucket.get() == null) rgbucket.set(user, 30, TimeUnit.MINUTES);

        return user;
    }

    public Store getStore() {
        logger.debug("=========getUser");
        if (ObjectUtil.getSid() == null) return null;
        return getStore(ObjectUtil.getSid());
    }

    public Store getStore(Long sid) {
        logger.debug("=========getStore with sid=" + sid);
        // 1、获取mapp
        if (sid == null) return null;

        String rkey = Constants.REDIS_APP_STORE + sid;
        logger.debug("=========getStore rkey=" + rkey);
        RBucket<Store> bucket = redis.getBucket(rkey);

        Store store = bucket.isExists() ? bucket.get() : storeService.selectById(sid);
        if (store == null) return null;

        if (bucket.get() == null) bucket.set(store, 10, TimeUnit.MINUTES);
        return store;
    }

//    public Fenxiao getFenxiao() {
//        logger.debug("=========getUser");
//        // 1、获取mapp
//        Long mpid = ObjectUtil.getMpid();
//        Long uid = ObjectUtil.getUid();
//
//        String rkey = Constants.REDIS_APP_FENXIAO + mpid;
//        logger.debug("=========getFenxiao rkey=" + rkey);
//        RBucket<Fenxiao> bucket = redis.getBucket(rkey);
//
//        Fenxiao fenxiao = bucket.isExists() ? bucket.get() : fenxiaoService.selectOne(new EntityWrapper<Fenxiao>().eq("mpid", mpid));
//        if (fenxiao == null) return null;
//
//        logger.debug("--------------------------------------==redis=set=fenxiao=" + fenxiao);
//        if (bucket.get() == null) bucket.set(fenxiao, 30, TimeUnit.MINUTES);
//
//        return fenxiao;
//    }

    public Long getLeagueid() {
        return getUser()==null?null:getUser().getLeagueid();
    }

    public Long getLeagueid(Long sid) {
        Long leagueid = null;
        if (sid == null) return leagueid;
        String rkey = Constants.REDIS_STORE_LEAGUE + sid;
        logger.debug("=========getLeagueid rkey=" + rkey);
        RBucket<Long> bucket = redis.getBucket(rkey);
        if (bucket.isExists()) return bucket.get();

        Store store = storeService.selectOne(new EntityWrapper<Store>().setSqlSelect("id,leagueid").eq("id", sid));
        if (store == null) return null;
        leagueid = store.getLeagueid();
        if (leagueid != null) bucket.set(leagueid, 30, TimeUnit.MINUTES);
        return leagueid;
    }

    //联盟管理员
    public Long getLeagueAdminuser() {
        Long leagueid = getLeagueid();
        if (leagueid == null) return null;

        String rkey = Constants.REDIS_LEAGUE_ADMIN + leagueid;
        logger.debug("=========getUser rkey=" + rkey);
        RBucket<Long> bucket = redis.getBucket(rkey);
        if (bucket.isExists()) return bucket.get();

        //联盟用户
        User user = userService.getLeagueUserbyLeagueid(leagueid);

        if (user == null) return null;

        bucket.set(user.getId(), 10, TimeUnit.MINUTES);
        return user.getId();
    }

    //联盟管理员
    public Long getLeagueAdminuser(Long sid) {
        Long leagueid = getLeagueid();
        if (leagueid == null) return null;

        String rkey = Constants.REDIS_LEAGUE_ADMIN + sid;
        logger.debug("=========getUser rkey=" + rkey);
        RBucket<Long> bucket = redis.getBucket(rkey);
        if (bucket.isExists()) return bucket.get();

        //联盟用户
        User user = userService.getLeagueUserbySid(sid);

        if (user == null) return null;

        bucket.set(user.getId(), 10, TimeUnit.MINUTES);
        return user.getId();
    }

    //商家管理员
    public Long getStoreAdminuser(Long sid) {
        Long uid = null;
        if (sid == null) return uid;
        String rkey = Constants.REDIS_STORE_ADMIN + sid;
        logger.debug("=========getUser rkey=" + rkey);

        RBucket<Long> bucket = redis.getBucket(rkey);
        if (bucket.isExists()) return bucket.get();

        User user = userService.getLeagueUserbySid(sid);

        if (user == null) return null;
        uid = user.getId();
        bucket.set(uid, 10, TimeUnit.MINUTES);
        return uid;
    }

    public void delUser() {
        logger.debug("=========getUser");
        // 1、获取mapp
        Long uid = ObjectUtil.getUid();

        delUser(uid);
    }

    public void delUserByguid(String guid) {
        logger.debug("=========getUser");
        // 1、获取mapp
        if (Strings.isNullOrEmpty(guid)) return;

        String rkey = Constants.REDIS_APP_USER_GUID + guid;
        logger.debug("=========getUser rkey=" + rkey);
        RBucket<User> bucket = redis.getBucket(rkey);

        if (bucket.isExists()) bucket.delete();
    }

    public void delUser(Long uid) {
        logger.debug("=========getUser");
        // 1、获取mapp
        if (uid == null) return;

        String rkey = Constants.REDIS_APP_USER + uid;
        logger.debug("=========getUser rkey=" + rkey);
        RBucket<User> bucket = redis.getBucket(rkey);

        if (bucket.isExists()) bucket.delete();
    }

    public User getUserByGuid(String guid) {
        logger.debug("=========getUserByGuid");
        // 1、获取mapp
        String rgkey = Constants.REDIS_APP_USER_GUID + guid;
        RBucket<User> rgbucket = redis.getBucket(rgkey);
        logger.debug("=========getUserByGuid rgkey=" + rgkey);
        User user = rgbucket.isExists() ? rgbucket.get() :null;
        if(user==null){
            int cout = userService.selectCount(new EntityWrapper<User>().eq("guid", guid));
            if(cout==1)user = userService.selectOne(new EntityWrapper<User>().eq("guid", guid));
        }

        if (rgbucket.get() == null && user != null) rgbucket.set(user, 30, TimeUnit.MINUTES);

        return user;
    }

    public User getUserByOpenid(String openid) {
        logger.debug("=========getUserByOpenid");
        // 1、获取mapp
        String rgkey = Constants.REDIS_APP_USER_OPENID + openid;
        RBucket<User> rgbucket = redis.getBucket(rgkey);
        logger.debug("=========getUserByOpenid rgkey=" + rgkey);
        User user = rgbucket.isExists() ? rgbucket.get() :
                userService.selectOne(new EntityWrapper<User>().eq("openid", openid));
        if (rgbucket.get() == null && user != null) rgbucket.set(user, 30, TimeUnit.MINUTES);

        return user;
    }

    public MerchantApp getMApp() {
        logger.debug("=========getMApp()");
        Long mpid = ObjectUtil.getMpid();
        logger.debug("==================getMApp() mpid=" + mpid);
        if (mpid == null) return null;

        return getMApp(mpid);
    }

    public MerchantApp getMApp(Long mpid) {
        logger.debug("=========getMApp(mpid) mpid=" + mpid);
        if (mpid == null) return null;
        String rkey = Constants.REDIS_MERCHANT_APP + mpid;
        logger.debug("=========getMApp rkey=" + rkey);
        MerchantApp mapp = null;
        RBucket<MerchantApp> bucket = redis.getBucket(rkey);
        try {
            mapp = bucket.isExists() && bucket.get().getId() > 0 ? bucket.get() : merchantAppService.selectOne(new EntityWrapper<MerchantApp>()
                    .setSqlSelect("id,name,appid,mid,mchid,mpcode,mcode,sid,appsecret,paykey,aeskey,aesiv,token,asmpid,iscdn," +
                            "app_type appType,version_type version,kefuzj,kefu1,kefu2,smsappid,smsappkey,aspaympid,servmchid,servappid").eq("id", mpid));
            if (bucket.get() == null && mapp != null) bucket.set(mapp);
        } catch (Exception e) {
            logger.error("======getMconfig error", e);
        }
        return mapp;
    }

    public MerchantConfig getMconfig() {
        logger.debug("=========getMconfig");
        // 1、获取mapp
        Long mpid = ObjectUtil.getMpid();
        return getMconfig(mpid);
    }

    public MerchantConfig getMconfig(Long mpid) {
        logger.debug("=========getMconfig");
        // 1、获取mapp

        String rkey = Constants.REDIS_MERCHANT_CONFIG + mpid;
        logger.debug("=========getMconfig mpid=" + mpid);
        logger.debug("=========getMconfig rkey=" + rkey);
        MerchantConfig mconfig = null;
        try {
            RBucket<MerchantConfig> bucket = redis.getBucket(rkey);
            mconfig = bucket.isExists() && bucket.get().getId() > 0 ? bucket.get() : merchantConfigService.selectOne(new EntityWrapper<MerchantConfig>().eq("mpid", mpid));

            logger.debug("=========mconfig=" + JSON.toJSONString(mconfig));
            if (bucket.get() == null && mconfig != null) bucket.set(mconfig);
        } catch (Exception e) {
            logger.error("======getMconfig error", e);
        }
        return mconfig;
    }

    public FanConfig getFanconfig(Long mpid) {
        logger.debug("=========getMconfig");
        // 1、获取mapp
        String rkey = Constants.REDIS_FAN_CONFIG + mpid;
        logger.debug("=========getFanconfig rkey=" + rkey);
        FanConfig fconfig = null;

        try {
            RBucket<FanConfig> bucket = redis.getBucket(rkey);
            fconfig = bucket.isExists() && bucket.get().getId() > 0 ? bucket.get() :
                    fanConfigService.selectOne(new EntityWrapper<FanConfig>().eq("mpid", mpid));

            logger.debug("=========mconfig=" + JSON.toJSONString(fconfig));
            if (bucket.get() == null && fconfig != null) bucket.set(fconfig);

        } catch (Exception e) {
            logger.error("======getMconfig error", e);
        }

        return fconfig;
    }

    public String getOem(Long mpid, String guid) {
        String rkey = Constants.REDIS_OEM + mpid + "_" + guid;
        String result = get(rkey);
        logger.debug("--------------getOem rkey =" + rkey);

        if (!Strings.isNullOrEmpty(result) && !result.equals("null")) {
            return result;
        }

        User user = getUserByGuid(ObjectUtil.getGuid());
        logger.debug("--------------getOem user=" + user);
        if (user != null && ((user.getIsOem() != null && user.getIsOem() == 1) ||
                (user.getIsAdmin() != null && user.getIsAdmin() == 1) ||
                (user.getIsStaff() != null && user.getIsStaff() == 1))) {
            Merchant merchant = merchantService.selectById(user.getMid());
            result = merchant.getZcname();
            logger.debug("--------------------------------------getOem 111 result =" + result);
            if (!Strings.isNullOrEmpty(result)) {
                set(rkey, result, 30, TimeUnit.MINUTES);
                return result;
            }
        }

        if (user != null && !Strings.isNullOrEmpty(user.getPhone())) {
            user = userService.selectOne(new EntityWrapper<User>()
                    .eq("phone", user.getPhone())
                    .eq("is_oem", 1)
            );
        }
        if (user != null) {
            Merchant merchant = merchantService.selectById(user.getMid());
            result = merchant.getZcname();
            logger.debug("--------------------------------------===getOem 222 result =" + result);
            if (!Strings.isNullOrEmpty(result)) {
                set(rkey, result, 30, TimeUnit.MINUTES);
                return result;
            }
        }

        logger.debug("=========getOem user is null");
        Oem oem = oemService.selectOne(new EntityWrapper<Oem>().eq("guid", guid));
        if (oem != null) {
            logger.debug("=========getOem oem=" + oem);
            result = oem.getOem();
        }

        if (Strings.isNullOrEmpty(result)) result = "北京仟牛互动";
        return result;
    }

    public String getOemphone(Long mpid, String guid) {
        String rkey = Constants.REDIS_OEM_PHONE + mpid + "_" + guid;
        boolean islogin = false;
        String result = get(rkey);
        if (!Strings.isNullOrEmpty(result)) {
            return result;
        }

        User user = getUserByGuid(ObjectUtil.getGuid());
        logger.debug("===============getOem user=" + user);
        if (user != null && ((user.getIsOem() != null && user.getIsOem() == 1) ||
                (user.getIsAdmin() != null && user.getIsAdmin() == 1) ||
                (user.getIsStaff() != null && user.getIsStaff() == 1))) {
            Merchant merchant = merchantService.selectById(user.getMid());
            result = merchant.getZcphone();
            islogin = true;
            set(rkey, result, 30, TimeUnit.MINUTES);
            return result;
        }

        if (user != null && !Strings.isNullOrEmpty(user.getPhone())) {
            user = userService.selectOne(new EntityWrapper<User>()
                    .eq("phone", user.getPhone())
                    .eq("is_oem", 1)
            );
        }
        if (user != null) {
            Merchant merchant = merchantService.selectById(user.getMid());
            result = merchant.getZcphone();
            set(rkey, result, 30, TimeUnit.MINUTES);
            return result;
        }

        logger.debug("=========getOem user is null");
//        Oem oem = oemService.selectOne(new EntityWrapper<Oem>().eq("guid", guid));
//        if (oem != null) {
//            logger.debug("=========getOem oem=" + oem);
//            result = oem.getOem();
//        }

        if (Strings.isNullOrEmpty(result)) result = "";
        return result;
    }

    public String getWxtoken() {
        logger.debug("=========getWxtoken");
        // 1、获取mapp
        MerchantApp mapp = getMApp();
        if (mapp == null) return null;

        String rkey = Constants.REDIS_WX_TOKEN + mapp.getAppid();
        RBucket<String> bucket = redis.getBucket(rkey);
        String token = bucket.get();
        if (!Strings.isNullOrEmpty(token)) return token;

        try {
            String url = Constants.WX_URL_TOKEN.replace("APPID", mapp.getAppid()).replace("SECRET", mapp.getAppsecret());
            String rt = HttpUtil.sendGet(url, null);
            JSONObject json = JSONObject.parseObject(rt);
            if (json.getString("access_token") != null || json.getString("access_token") != "") {
                token = json.getString("access_token");
                Integer expires = json.getInteger("expires_in");
                bucket.set(token, expires, TimeUnit.SECONDS);
            } else {
                return null;
            }
        } catch (Exception e) {
            logger.error("# 获取 token 出错... e:" + e);
            return null;
        }
        logger.debug("=========token=" + token);
        return token;
    }

    public String getWxtoken(String mpid) {
        if (Strings.isNullOrEmpty(mpid)) return "";
        MerchantApp mapp = getMApp(Long.valueOf(mpid));
        if (mapp == null || Strings.isNullOrEmpty(mapp.getAppid())) return "";

        String rkey = Constants.REDIS_WX_TOKEN + mapp.getAppid();
        RBucket<String> buckets = redis.getBucket(rkey);
        String token = buckets.get();
        if (!Strings.isNullOrEmpty(token)) return token;

        try {
            String url = Constants.WX_URL_TOKEN.replace("APPID", mapp.getAppid()).replace("SECRET", mapp.getAppsecret());
            String rt = HttpUtil.sendGet(url, null);
            JSONObject json = JSONObject.parseObject(rt);
            if (json.getString("access_token") != null || json.getString("access_token") != "") {
                token = json.getString("access_token");
                Integer expires = json.getInteger("expires_in");
                buckets.set(token, expires, TimeUnit.SECONDS);
            } else {
                return null;
            }
        } catch (Exception e) {
            logger.error("# 获取 token 出错... e:" + e);
            return null;
        }
        logger.debug("=========token=" + token);
        return token;
    }

    public String getWxactoken(String mpid) {
        logger.debug("=========getWxactoken");
        // 1、获取mapp
        MerchantApp mapp = getMApp(Long.valueOf(mpid));
        if (mapp == null) return null;

        String token = mapp.getToken();
        logger.debug("=========token=" + token);
        return token;
    }

}
